;; this file is responsible for setting up paging with the kernel in
;; the higher half. 
;; Kernel appears at 0xC0000000 
;; Heap appears at   0xD0000000
;; Stack appears at  0xE0000000

global _cr1
global pde_virt
extern kmain
extern gdtr
[bits 32]
[section .cr1_text]

;;; this is here because the table are linked in at the
;;; end of the kernel, and their addresses have this offset
OFFSET	equ	0xc0000000

;;; set by linker. marks beginning of free memory
extern END

_cr1:
	xor eax, eax
	mov eax, 0x10
	mov ds, ax
	mov es, ax
	mov ss, ax
	mov esp, 0x000ffff
	mov fs, ax
	mov gs, ax

;;; setup paging
	mov ebx, END
	or ebx, 0x3
	mov ecx, 0
	mov eax, 0x00000003
	mov edx, 0x00400003

loop:	mov dword [pte1 + ecx*4 - OFFSET], eax
	mov dword [pte2 + ecx*4 - OFFSET], edx
	mov dword [heap_pte + ecx*4 - OFFSET], ebx
	add eax, 0x1000
	add edx, 0x1000
	add ebx, 0x1000
	inc ecx
	cmp ecx, 1024
	jz end
	jmp loop
	
end:	mov eax, (pte1 - OFFSET)
	mov edx, (pte2 - OFFSET)
	mov ebx, (heap_pte - OFFSET)
	or eax, 0x00000003
	or edx, 0x00000003
	or ebx, 0x00000003

	;;;  identity map first 4 mb
	mov dword [pde_phys - OFFSET], eax
	mov dword [pde_phys + 4 - OFFSET], edx

	;;;  also map 0xC0000000 => 0x00000000
	mov dword [pde_phys + 768*4 - OFFSET], eax
	mov dword [pde_phys + 769*4 - OFFSET], edx

	;;; map 0xD0000000 => END_OF_KERNEL
	mov dword [pde_phys + 832*4 - OFFSET], ebx

        ;;; now do the same thing as above, but setup
        ;;; the virtual address in the pde so we can
        ;;; read the tables
	add eax, OFFSET
	add edx, OFFSET
	add ebx, OFFSET
	mov dword [pde_virt - OFFSET], eax
	mov dword [pde_virt + 4 - OFFSET], edx
	mov dword [pde_virt + 768*4 - OFFSET], eax
	mov dword [pde_virt + 769*4 - OFFSET], edx
	mov dword [pde_virt + 832*4 - OFFSET], ebx
	
	mov eax, (pde_phys - OFFSET)
	mov cr3, eax
	mov eax, cr0
	or eax, 0x80000000
	mov cr0, eax

	;; reload gdtr with updated address to account for paging
	;; 	mov eax, [gdtr + 2]
				;	add eax, 0xC0000000
				;	mov [gdtr + 2], eax
	;; 	lgdt [gdtr]

blank:	nop
	nop
	nop
	
	call kmain


;;; these will later be stored in data structures to be
;;; accessed by the kernel. This way we can set them up
;;; here, and just point to them when we initialise paging
[section .cr1_data]
pde_virt: times 1024 dd 0

pde_phys: times 1024 dd 0

;;; maps 0-4 MB
pte1: times 1024	 dd 0

;;; maps 4-8 MB
pte2: times 1024	 dd 0

;;; maps page tables for the heap
heap_pte: times 1024 	 dd 0

;;; stack page table
stack_pte times 1024 	 dd  0

